package com.xian.cloud.config;

import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
import sun.net.www.protocol.https.DefaultHostnameVerifier;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Author: xlr
 * @Date: Created in 下午11:16 2019/1/8
 */
@Component
public class OkHttpClientUtil {

    private static final Logger log = LoggerFactory.getLogger( OkHttpClientUtil.class );

    private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");

    //private static  String SELFCERTPATH = null;

//    @Value("${nb.secret.selfcertpath}")
//    public void setSelfcertpath(String selfcertpath) {
//        SELFCERTPATH = selfcertpath;
//    }
//    private static  String TRUSTCAPATH = null;
//
//    @Value("${nb.secret.trustcapath}")
//    public void setTrustcapath(String trustcapath) {
//        TRUSTCAPATH = trustcapath;
//    }
//    private static  String SELFCERTPWD = null;
//
//    @Value("${nb.secret.selfcertpwd}")
//    public void setSelfcertpwd(String selfcertpwd) {
//        SELFCERTPWD = selfcertpwd;
//    }
//    private static  String TRUSTCAPWD = null;
//
//    @Value("${nb.secret.trustcapwd}")
//    public void setTrustcapwd(String trustcapwd) {
//        TRUSTCAPWD = trustcapwd;
//    }
//


    /**
     * 获取okHttpClient
     *
     * @return
     */
    private static OkHttpClient getOkHttpClient(){
        return new OkHttpClient.Builder()
                //.sslSocketFactory(getSslSocketFactory(), getX509TrustManager())
                .hostnameVerifier(new DefaultHostnameVerifier())
                .retryOnConnectionFailure(false)//是否开启缓存
                .connectionPool(getConnectionPool())
                .connectTimeout(5000, TimeUnit.MILLISECONDS)
                .readTimeout(5000, TimeUnit.MILLISECONDS)
                .writeTimeout(5000, TimeUnit.MILLISECONDS)
                //.addInterceptor(new NbTokenInterceptor())//拦截器
                .build();
    }

    private static X509TrustManager getX509TrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }
//
//    private static SSLSocketFactory getSslSocketFactory() {
//        SSLSocketFactory ssl = null;
//        try {
//            System.out.println(ResourceUtils.getURL("classpath:").getPath());
//
//
//            ClassPathResource selfcertPath = new ClassPathResource(SELFCERTPATH);
//            ClassPathResource trustcaPath = new ClassPathResource(TRUSTCAPATH);
//            KeyStore selfCert = KeyStore.getInstance("pkcs12");
//            selfCert.load(selfcertPath.getInputStream(), SELFCERTPWD.toCharArray());
//            KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
//            kmf.init(selfCert, SELFCERTPWD.toCharArray());
//
//            // 导入CA证书
//            KeyStore caCert = KeyStore.getInstance("jks");
//            caCert.load(trustcaPath.getInputStream(), TRUSTCAPWD.toCharArray());
//            TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509");
//            tmf.init(caCert);
//
//            SSLContext sc = SSLContext.getInstance("TLS");
//            sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
//            ssl = sc.getSocketFactory();
//
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//
//        return ssl;
//    }

    private static ConnectionPool getConnectionPool() {
        /**
         * maxIdleConnections 连接池中整体的空闲连接的最大数量
         * keepAliveDuration 连接空闲时间最多为五分钟
         */
        return new ConnectionPool(500, 5, TimeUnit.MINUTES);
    }

    /**
     * 执行同步Get请求
     */
    public static Response executeGet(String url, Map<String, String> headers) throws IOException {
        //构建请求
        Request.Builder requestBuilder = new Request.Builder().url(url);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        return response;
    }

    /**
     * 执行异步Get请求
     *
     * @param url  请求路径
     * @param headers  请求头
     * @param callback  回调方法
     * @throws IOException
     */
    public static void enqueueGet(String url, Map<String, String> headers, Callback callback) throws IOException {
        //构建请求
        Request.Builder requestBuilder = new Request.Builder().url(url);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        okHttpClient.newCall(request).enqueue(callback);
    }

    /**
     * 执行同步PostForm请求
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws IOException
     */
    public static Response executePostForm(String url, Map<String, String> params, Map<String, String> headers) throws IOException {
        //构造请求体
        FormBody.Builder formBodyBuilder = new FormBody.Builder();
        if(!CollectionUtils.isEmpty(params)){
            for (Map.Entry<String, String> mapEntry : params.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    formBodyBuilder.add(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //创建requestBody
        RequestBody requestBody = formBodyBuilder.build();
        Request.Builder requestBuilder = new Request.Builder().url(url).post(requestBody);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        log.info(url + " postForm response-->" + response.code());
        return response;
    }

    /**
     * 执行同步PostJSON请求
     * @param url
     * @param jsonStr
     * @param headers
     * @return
     * @throws IOException
     */
    public static Response executePostJSON(String url, String jsonStr, Map<String, String> headers) throws IOException {
        //构造请求体
        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, jsonStr);
        //创建requestBody
        Request.Builder requestBuilder = new Request.Builder().url(url).post(requestBody);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        log.info(url + " postJSON response-->" + response.code());
        return response;
    }

    /**
     * 执行同步PutJSON请求
     * @param url
     * @param jsonStr
     * @param headers
     * @return
     * @throws IOException
     */
    public static Response executePutJSON(String url, String jsonStr, Map<String, String> headers) throws IOException {
        //构造请求体
        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, jsonStr);
        //创建requestBody
        Request.Builder requestBuilder = new Request.Builder().url(url).put(requestBody);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        log.info(url + " putJSON response-->" + response.code());
        return response;
    }

    /**
     * 执行同步PutForm请求
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws IOException
     */
    public static Response executePutForm(String url, Map<String, Object> params, Map<String, String> headers) throws IOException {
        //构造请求体
        FormBody.Builder formBodyBuilder = new FormBody.Builder();
        if(!CollectionUtils.isEmpty(params)){
            for (Map.Entry<String, Object> mapEntry : params.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    formBodyBuilder.add(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //创建requestBody
        RequestBody requestBody = formBodyBuilder.build();
        Request.Builder requestBuilder = new Request.Builder().url(url).put(requestBody);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        log.info(url + " putForm response-->" + response.code());
        return response;
    }

    /**
     * 执行同步DeleteJSON请求
     * @param url
     * @param jsonStr
     * @param headers
     * @return
     * @throws IOException
     */
    public static Response executeDeleteJSON(String url, String jsonStr, Map<String, String> headers) throws IOException {
        if(StringUtils.isEmpty(jsonStr)){
            return executeDelete(url, headers);
        }
        //构造请求体
        RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, jsonStr);
        //创建requestBody
        Request.Builder requestBuilder = new Request.Builder().url(url).delete(requestBody);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        log.info(url + " deleteJSON response-->" + response.code());
        return response;
    }

    /**
     * 执行同步DeleteForm请求
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws IOException
     */
    public static Response executeDeleteForm(String url, Map<String, String> params, Map<String, String> headers) throws IOException {
        //构造请求体
        FormBody.Builder formBodyBuilder = new FormBody.Builder();
        if(!CollectionUtils.isEmpty(params)){
            for (Map.Entry<String, String> mapEntry : params.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    formBodyBuilder.add(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //创建requestBody
        RequestBody requestBody = formBodyBuilder.build();
        Request.Builder requestBuilder = new Request.Builder().url(url).delete(requestBody);
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        log.info(url + " deleteForm response-->" + response.code());
        return response;
    }

    /**
     * 执行同步Delete请求
     * @param url
     * @param headers
     * @return
     * @throws IOException
     */
    public static Response executeDelete(String url, Map<String, String> headers) throws IOException {
        //创建requestBody
        Request.Builder requestBuilder = new Request.Builder().url(url).delete();
        //构造请求头
        if(!CollectionUtils.isEmpty(headers)){
            for (Map.Entry<String, String> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client
        OkHttpClient okHttpClient = getOkHttpClient();
        //执行
        Response response = okHttpClient.newCall(request).execute();

        log.info(url + " delete response-->" + response.code());
        return response;
    }

    /**
     * 获取response code
     * @param response
     * @return
     */
    public static int getResponseCode(Response response){
        return response.code();
    }

    /**
     * 获取resoponse body
     * @param response
     * @return
     * @throws IOException
     */
    public static String getResponseBody(Response response) throws IOException {
        if(response.isSuccessful() && response.code() == 200){
            return response.body().string();
        }

        return null;
    }

    /**
     * 获取resoponse body
     * @param response
     * @param code
     * @return
     * @throws IOException
     */
    public static String getResponseBody(Response response, int code) throws IOException {
        if(response.isSuccessful() && response.code() == code){
            return response.body().string();
        }

        return null;
    }

    /**
     * 上传单个文件
     * @param url
     * @param params
     * @param headers
     * @return
     */
    public static Response executeMultipart(String url, Map<String, Object> params, Map<String, Object> headers, File file){

        //构建请求
        MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);

        if (file != null) {
            // MediaType.parse() 里面是上传的文件类型。
            RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data; charset=utf-8"), file);
            String filename = file.getName();
            // 参数分别为， 请求key ，文件名称 ， RequestBody
            requestBodyBuilder.addFormDataPart("file", file.getName(), body);
        }
        //请求参数
        if(params != null && !params.isEmpty()){
            for (Map.Entry<String, Object> mapEntry : params.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBodyBuilder.addFormDataPart(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //创建requestBody
        RequestBody requestBody = requestBodyBuilder.build();

        Request.Builder requestBuilder = new Request.Builder().url(url).post(requestBody);
        //构造请求头
        if(headers != null && !headers.isEmpty()){
            for (Map.Entry<String, Object> mapEntry : headers.entrySet()) {
                // value不为空
                if(!Objects.isNull(mapEntry.getValue())){
                    requestBuilder.addHeader(mapEntry.getKey(), String.valueOf(mapEntry.getValue()));
                }
            }
        }
        //构建请求
        Request request = requestBuilder.build();
        //获取client,上传文件设置超时时间300s
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .writeTimeout(300, TimeUnit.SECONDS)
                .build();
        //执行
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return response;
    }

    public static void main(String[] args) throws IOException {

        Response response = OkHttpClientUtil.executeGet( "http://wwww.baidu.com", new HashMap <String, String>());

        ResponseBody body = response.body();

        int code = response.code();

        boolean successful = response.isSuccessful();

        String message = response.message();

        Request request = response.request();

        try {
            System.out.println(request.method());
            System.out.println(successful);
            System.out.println(code);
            System.out.println(body.string());

            System.out.println(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}